public class StockOrder extends AbstractOrder {
	private static boolean toggle = true;

	public StockOrder() {
		setInitializedState(new OrderInitializedState(this));
		setActiveState(new OrderActiveState(this));
		setPartialState(new OrderPartialState(this));
		setClosedState(new OrderClosedState(this));
	}

	@Override
	public void createOrder(int orderId, OrderCategory orderCategory,
			int accountId, int portfolioId) {
		setAccountId(accountId);
		setOrderId(orderId);
		setOrderCategory(orderCategory);
		setPortfolioId(portfolioId);

		StockRepository stockRepository = StockRepository.getStockRepository();
		Stock stock = stockRepository.getStock(getStockId());
		if (stock != null) {
			double stockPrice = stock.getStockPrice();
			setSecurityPrice(stockPrice);
		} else {
			System.out.println("Stock does not exists! ");
		}
	}

	@Override
	public void display() {
		System.out.println("\nOrder Id: " + getOrderId());
		System.out.println("Stock Id: " + getStockId());
		System.out.println("Order Type: " + getOrderType());
		System.out.println("Order Category: " + getOrderCategory());
		System.out.println("Stock Price: " + getSecurityPrice());
		System.out.println("Quantity: " + getQuantity());
	}

	@Override
	public void updateOrder(StockValueObserver buyer,
			StockValueObserver seller, int matchedQuantity) {
		if (toggle) {
			AbstractOrder buyerOrder = ((ActiveOrder) buyer).getOrder();
			AbstractOrder sellerOrder = ((ActiveOrder) seller).getOrder();

			boolean isBuyerOrderFulfilled = (buyerOrder.getQuantity() == buyerOrder
					.getFulfilledQuantity());
			boolean isSellerOrderFulfilled = (sellerOrder.getQuantity() == sellerOrder
					.getFulfilledQuantity());
			System.out.println("Updating states in Order: ");
			if (isBuyerOrderFulfilled && isSellerOrderFulfilled) {
				buyerOrder.closeOrder(true);
				sellerOrder.closeOrder(true);
			} else if (isBuyerOrderFulfilled && !isSellerOrderFulfilled) {
				buyerOrder.closeOrder(true);
				sellerOrder.partialOrder();
			} else if (!isBuyerOrderFulfilled && isSellerOrderFulfilled) {
				buyerOrder.partialOrder();
				sellerOrder.closeOrder(true);
			}
			System.out.println("Update Active Orders! ");
			toggle = false;
		} else {
			toggle = true;
		}
	}

	@Override
	public void setState(OrderState orderState) {
		setOrderState(orderState);
	}

	@Override
	public void initializeOrder() {
		if (getOrderState() == null) {
			getInitializedState().initializeOrder();
		} else {
			getOrderState().initializeOrder();
		}
	}

	@Override
	public void activeOrder() {
		getOrderState().activeOrder();
	}

	@Override
	public void partialOrder() {
		getOrderState().partialOrder();
	}

	@Override
	public void closeOrder(boolean isOrderFulfilled) {
		getOrderState().closeOrder(isOrderFulfilled);
	}

	@Override
	public OrderState getOrderInitializedState() {
		return getInitializedState();
	}

	@Override
	public OrderState getOrderActiveState() {
		return getActiveState();
	}

	@Override
	public OrderState getOrderClosedState() {
		return getClosedState();
	}

	@Override
	public OrderState getOrderPartialState() {
		return getPartialState();
	}

	public AbstractOrder newStockOrder(AbstractOrder order) {
		AbstractOrder newOrder = new StockOrder();
		int newOrderId = Request.orderId + 1;
		newOrder.setOrderId(newOrderId);
		newOrder.setStockId(order.getStockId());
		newOrder.setAccountId(order.getAccountId());
		newOrder.setEndTime(order.getEndTime());
		newOrder.setFulfilledQuantity(order.getFulfilledQuantity());
		newOrder.setOrderCategory(order.getOrderCategory());
		newOrder.setOrderPrice(order.getOrderPrice());
		newOrder.setOrderType(order.getOrderType());
		newOrder.setPortfolioId(order.getPortfolioId());
		newOrder.setPriceLimit(order.getPriceLimit());
		newOrder.setQuantity(order.getQuantity());
		newOrder.setSecurityPrice(order.getSecurityPrice());
		newOrder.setSecurityType(order.getSecurityType());
		newOrder.setStartTime(order.getStartTime());
		newOrder.setTimestamp(order.getTimestamp());
		return newOrder;
	}
}
